#include <iostream>
#include <new>
#include <cstdlib>
#include <cctype>
#include <malloc.h>
#include <vector>
#include "performance.h"
#include "memorypool.h"
#include "mobject.h"
using namespace std;

class MemoryUse
{
public:
    static void report( const char* desc = 0 )
    {
#if defined WIN_NT || sun
        cerr<<"mallinfo not available on this platform."<<endl;
#else
        struct mallinfo mi = mallinfo();
        if( desc )
        {
            cout<<"\n=======   "<<desc<<"   ======\n";
        }
        cout<<"Arena:"<<mi.arena<<" Used blocks:"<<mi.uordblks<<endl;
#endif
    }

};


class IOBkt:public MObject
{
    char mem[316];
public:
    IOBkt()
    {
        //cout<<"Constructor"<<endl;
    }
};

class IO:public MObject
{
    char mem[148];
};

int main( int argc, char** argv )
{
try{

    int nIo = atoi( argv[1] );
    int nBkt = atoi( argv[2] );

    vector< IO* > ioVec;
    vector< IOBkt* > bktVec;

    cout<<"IO="<<nIo<<" Bkt="<<nBkt<<endl;
    Performance regPerf( "Normal ");
    regPerf.start();
    // Normal allocate
    for( int i=0; i<nIo; i++ )
    {
        IO* io = new IO();
        ioVec.push_back( io );
        //cout<<"#"<<i<<endl;
        for( int j=0; j<nBkt; j++ )
        {
            IOBkt* bkt = new IOBkt();
            //cout<<"\t"<<j<<endl;
            bktVec.push_back( bkt );
        }
    }
    regPerf.stop();
    regPerf.report();

    regPerf.start();
    // Clear Normal allocate
    for( vector< IO* >::iterator i = ioVec.begin();
         i != ioVec.end();
         i++ )
    {
        delete (*i);
    }

    for( vector< IOBkt* >::iterator i = bktVec.begin();
         i != bktVec.end();
         i++ )
    {
        delete (*i);
    }
    regPerf.stop();
    regPerf.report();
    MemoryUse::report();
    ioVec.clear();
    bktVec.clear();

    MObject::destroyMemoryPool();

    Performance plPerf( "MemoryPool");
    plPerf.start();
    MemoryPool memPool;
    plPerf.stop();
    plPerf.report();
    plPerf.start();
    // Normal allocate
    for( int i=0; i<nIo; i++ )
    {
        IO* io = (IO*)memPool.allocate(sizeof(IO));
        ioVec.push_back( io );
        //cout<<"#"<<i<<endl;
        for( int j=0; j<nBkt; j++ )
        {
            IOBkt* bkt = (IOBkt*)memPool.allocate(sizeof(IOBkt));
            //cout<<"\t"<<j<<endl;
            bktVec.push_back( bkt );
        }
    }

    plPerf.stop();
    plPerf.report();

    plPerf.start();
#if 1
    // Clear Normal allocate
    for( vector< IO* >::iterator i = ioVec.begin();
         i != ioVec.end();
         i++ )
    {
        memPool.recycle(*i);
    }

    for( vector< IOBkt* >::iterator i = bktVec.begin();
         i != bktVec.end();
         i++ )
    {
        memPool.recycle(*i);
    }
#endif

    plPerf.stop();
    plPerf.report();
    ioVec.clear();
    bktVec.clear();

    MemoryUse::report("MemoryPool");
    //memPool.report();

}catch( MemoryException &e )
{
    cerr<<e.toString()<<endl;
}

    return 0;
}
